using System;
using System.Diagnostics;
using System.Linq;
using WatiN.Core;
using WatiN.Core.DialogHandlers;

namespace Budgeteer.Services
{
    public class BankService
    {
        public void DownloadTransactionFile(string url, string saveAsPath)
        {
            using (IE ie = new IE(url))
            {
                try
                {
                    PassDefaultPage(ie);
                    PassChallengePage(ie);
                    PassBalanceSheetPage(ie);
                    PassAccountDetailPage(ie);
                    SaveFile(ie,saveAsPath);
                }
                catch(ApplicationException ex)
                {
                    Debug.WriteLine(ex);
                }
            }
        }

        public bool PassDefaultPage(IE ie)
        {
            Element signInLink;

            if(ie.Elements.TryGetElement(new HtmlElementInfo { TagName="A",Title="Sign In to Online Banking" },out signInLink))
            {
                signInLink.Click();
                return true;
            }

            throw new ApplicationException("PassDefaultPage failed");
        }

        public bool PassChallengePage(IE ie)
        {
            Element passcodeTextBox;

            if (ie.Elements.TryGetElement(new HtmlElementInfo { TagName="INPUT", Id="passcode"}, out passcodeTextBox))
            {
                new TextField(passcodeTextBox) { Value = "passcode" };
                //passcode.KeyPress('\x0D');

                Element signInButton;
                if(ie.Elements.TryGetElement(new HtmlElementInfo { TagName="IMG",Title="Sign In",Name="sign_in" },out signInButton))
                {
                    signInButton.Click();
                    return true;
                }
            }

            throw new ApplicationException("PassChallengePage failed");
        }

        public bool PassBalanceSheetPage(IE ie)
        {
            Element accountLink;

            if(ie.Elements.TryGetElement(new HtmlElementInfo { TagName="A",Title="Show account detail for VC Signature Card #1234567890" },out accountLink))
            {
                accountLink.Click();
                return true;
            }

            throw new ApplicationException("PassBalanceSheetPage failed");
        }

        public bool PassAccountDetailPage(IE ie)
        {
            Element fileTypeDropdown;

            if(ie.Elements.TryGetElement(new HtmlElementInfo { TagName="SELECT",Id="filetype" },out fileTypeDropdown))
            {
                SelectList dropDown = new SelectList(fileTypeDropdown);
                dropDown.SelectByValue("Comma Delimited");

                Element downloadButton;
                if(ie.Elements.TryGetElement(new HtmlElementInfo { TagName="INPUT",Name="subButton",Value="Download" },out downloadButton))
                {
                    downloadButton.Click();
                    return true;
                }
            }

            throw new ApplicationException("PassAccountDetailPage failed");
        }

        public bool PassAccountDetailExportPage(IE ie)
        {
            Element continueButton;

            if(ie.Elements.TryGetElement(new HtmlElementInfo { TagName="INPUT",Value="Continue with download" },out continueButton))
            {
                continueButton.ClickNoWait();
                return true;
            }

            throw new ApplicationException("PassAccountDetailExportPage failed");
        }

        public bool SaveFile(IE ie, string path)
        {
            return SaveFile(ie, path, PassAccountDetailExportPage);
        }

        public bool SaveFile(IE ie, string path, Func<IE,bool> downloadButtonClick)
        {
            FileDownloadHandler fileDownloadHandler = new FileDownloadHandler("file.txt");
            ie.AddDialogHandler(fileDownloadHandler);
            Element continueButton;
            using(new UseDialogOnce(ie.DialogWatcher,fileDownloadHandler))
            {
                if(ie.Elements.TryGetElement(new HtmlElementInfo { TagName="INPUT",Value="Continue with download" },out continueButton))
                {
                    continueButton.ClickNoWait();
                    fileDownloadHandler.WaitUntilFileDownloadDialogIsHandled(15);
                    fileDownloadHandler.WaitUntilDownloadCompleted(200);
                    return true;
                }
            }
            return false;
        }
    }

    class HtmlElementInfo
    {
        public string TagName { get; set; }
        public string Id { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public string Alt { get; set; }
        public string Src { get; set; }
        public string Value { get; set; }
    }

    static class WatinExtensions
    {
        public static bool TryGetElement(this ElementCollection elements,HtmlElementInfo info,out Element found)
        {
            found = elements.SingleOrDefault(elm =>
            {
                Debug.WriteLine(elm.TagName + " " + elm.Title + " " + elm.InnerHtml);

                if(info.TagName != null && !info.TagName.Equals(elm.TagName))
                    return false;

                if(info.Id != null && !info.Id.Equals(elm.Id))
                    return false;

                if(info.Name != null && !info.Name.Equals(elm.GetValue("name")))
                    return false;

                if(info.Title != null && !info.Title.Equals(elm.Title))
                    return false;

                if(info.Alt != null && !info.Alt.Equals(elm.GetValue("alt")))
                    return false;

                if(info.Src != null && !info.Src.Equals(elm.GetValue("src")))
                    return false;

                if(info.Value != null && !info.Value.Equals(elm.GetValue("value")))
                    return false;

                return true;
            });
            return found != null;
        }
    }
}